#ifndef RP2VERTEXBUFFER_H
#define RP2VERTEXBUFFER_H

#include "Rp2Foundation.h"
#include "Rp2Object.h"
#include "Rp2Attributes.h"
#include "Rp2Bindable.h"

namespace Rp2
{
class VertexBuffer : public Object, public Bindable
{
public:
	VertexBuffer(const Attributes& rkAttr, int iVertexQuantity);
	VertexBuffer(const VertexBuffer* rkVBuffer);
	virtual ~VertexBuffer();

	// the format of a single vertex in the buffer
	const Attributes& GetAttributes() const;

	// the number of vertices in the buffer
	int GetVQuantity() const;

	// member access
	bool HasPostition() const;
	bool HasNormal() const;
	bool HasTCoord(int iUnit) const;
	int GetPositionOffset() const;
	int GetNormalOffset() const;
	int GetTCoordOffset(int iUnit) const;


	// Direct access to buffer data. The channel quantity
	// is the number of float elements.
	int GetChannelQuantity();
	float* GetData();
	const float* GetData() const;
	
    // Access to positions.
    float* PositionTuple (int i);
    const float* PositionTuple (int i) const;

    // Access to blend weights.
    float* BlendWeightTuple (int i);
    const float* BlendWeightTuple (int i) const;

    // Access to normals.
    float* NormalTuple (int i);
    const float* NormalTuple (int i) const;

    // Access to colors.
    float* ColorTuple (int iUnit, int i);
    const float* ColorTuple (int iUnit, int i) const;

    // Access to fog.
    float* FogTuple (int i);
    const float* FogTuple (int i) const;

    // Access to psize.
    float* PSizeTuple (int i);
    const float* PSizeTuple (int i) const;

    // Access to blend indices.
    float* BlendIndicesTuple (int i);
    const float* BlendIndicesTuple (int i) const;

    // Access to texture coordinates.
    float* TCoordTuple (int iUnit, int i);
    const float* TCoordTuple (int iUnit, int i) const;

    // Access to tangents.
    float* TangentTuple (int i);
    const float* TangentTuple (int i) const;

    // Access to bitangents.
    float* BitangentTuple (int i);
    const float* BitangentTuple (int i) const;

	// access for convenience 
	Vector3f& Position3(int i);
	Vector3f Position3(int i) const;

	Vector3f& Normal3(int i);
	Vector3f Normal3(int i) const;

	ColorRGB& Color3(int iUnit, int i);
	ColorRGB Color3(int iUnit, int i) const;
	
    float& TCoord1 (int iUnit, int i);
    float TCoord1 (int iUnit, int i) const;
    Vector2f& TCoord2 (int iUnit, int i);
    Vector2f TCoord2 (int iUnit, int i) const;
    Vector4f& TCoord4 (int iUnit, int i);
    Vector4f TCoord4 (int iUnit, int i) const;

	// compact vertex buffer data into a single float array
	void CompactData(const Attributes& rkIAttr, bool bPackedARGB, 
		int& riChannels, float*& rafOut) const;


    // An application might want to vary the "active quantity" of vertices.
    // Use this function to do so.  It does not change the data storage,
    // only the m_iVertexQuantity member.  The caller is responsible for
    // saving the full quantity of vertices and resetting this when finished
    // with the vertex buffer.  The caller also should not pass in a quantity
    // that is larger than the original full quantity.
    void SetVertexQuantity (int iVQuantity);

	// stream for debug
	void PrintToFile(const char* acFilename);

private:
	// attribute of a single vertex
	Attributes m_kAttributes;

	// the number of 'float' channels of a single vertex in the buffer
	int m_iVertexSize;

	// number of total vertices in the buffer
	int m_iVertexQuantity;
	
	// the vertex buffer data
	int m_iDataSize; // = m_iVertexQuantity * m_iVertexSize.
	float* m_afData;
};
#include "Rp2VertexBuffer.inl"

typedef Pointer<VertexBuffer> VertexBufferPtr;
}


#endif